Data Description

The data comprises of 58 inaugrual speeches, from that of George Washington to that of Donald Trump which was delivered earlier this year.

Research Question

First of all, I must admit that I am not good at politics, so I choose to tell my story just from the data itself and do not make any comment on politics.

The main question of my research is to analyse the trend of presidents’ inaugrual speeches according to the 58 inaugrual speeches we have from 1789-2017. Specifically, I want to tell a story from the following three aspects:

  1. Change in length of sentences in presidents’ inaugrual speeches
  2. Change in speakers’ emotions with presidents’ inaugrual speeches
  3. Change in topics of presidents’ inaugrual speeches

In order to analyse these changes of presidents’ inaugrual speeches in these years, I split the data into three parts according to the date of these speeches:
Period 1: 1789-1865, George Washington-Abraham Lincoln
Period 2: 1866-1945, Ulysses S. Grant-Franklin D. Roosevelt
Period 3: 1946-2017, Harry S. Truman-Donald J. Trump

In this report, I will focus my study on changes among speeches of these three periods and tell my own story.

Part I: Change in Length of Sentences

First, I look at the change in length of sentences of presidents’ inaugrual speeches.

Data Collection and Processing

Step 0: Check and install needed packages. Load the libraries and functions.

packages.used = c("rvest", "tibble", "qdap","sentimentr", "gplots", "dplyr", "tm", "syuzhet", "factoextra", "beeswarm", "scales", "RColorBrewer", "RANN", "tm", "topicmodels")
# check packages that need to be installed.
packages.needed=setdiff(packages.used, 
                        intersect(installed.packages()[,1], 
                                  packages.used))
# install additional packages
if(length(packages.needed)>0){
  install.packages(packages.needed, dependencies = TRUE)
}
# load packages
library("rvest")
library("tibble")
library("qdap")
library("sentimentr")
library("gplots")
library("dplyr")
library("tm")
library("syuzhet")
library("factoextra")
library("beeswarm")
library("scales")
library("RColorBrewer")
library("RANN")
library("tm")
library("topicmodels")
source("~/Desktop/CU_Stats/2018 Spring/GR5243 ADS/Project 1/wk2-TextMining/lib/plotstacked.R")
source("~/Desktop/CU_Stats/2018 Spring/GR5243 ADS/Project 1/wk2-TextMining/lib/speechFuncs.R")

Step 1: Read in the speeches

library("wordcloud")
library("tidytext")
library("readxl")
speech.list <- read_xlsx("~/Desktop/CU_Stats/2018 Spring/GR5243 ADS/Project 1/data/InaugurationInfo.xlsx")
speech.list$File <- paste(speech.list$File, speech.list$Term, sep = "-")
speech.list$File<- paste("inaug", speech.list$File, ".txt", sep = "")
speech.list$Period <- rep(1:3, c(20, 20, 18))
folder.path="~/Desktop/CU_Stats/2018 Spring/GR5243 ADS/Project 1/data/InauguralSpeeches/"
speeches=list.files(path = folder.path, pattern = "*.txt")
temp <- list.files(path = folder.path, pattern="*.txt")
speech.list$fulltext <- NA
for(i in 1:length(temp)){
speech.list$fulltext[i]<-paste(readLines(paste(folder.path,speech.list$File[i], sep = "")), collapse = " ")
}

Step 2: Generate list of sentences

sentence.list=NULL
for(i in 1:nrow(speech.list)){
  sentences=sent_detect(speech.list$fulltext[i],
                        endmarks = c("?", ".", "!", "|",";"))
  if(length(sentences)>0){
    emotions=get_nrc_sentiment(sentences)
    word.count=word_count(sentences)
    # colnames(emotions)=paste0("emo.", colnames(emotions))
    # in case the word counts are zeros?
    emotions=diag(1/(word.count+0.01))%*%as.matrix(emotions)
    sentence.list=rbind(sentence.list, 
                        cbind(speech.list[i,-ncol(speech.list)],
                              sentences=as.character(sentences), 
                              word.count,
                              emotions,
                              sent.id=1:length(sentences)
                              )
    )
  }
}
# Some non-sentences exist in raw data due to erroneous extra end-of sentence marks. 
sentence.list=
  sentence.list%>%
  filter(!is.na(word.count)) 

Data Analysis — Length of Sentences

Overview of sentence length distribution by different time periods of speeches

Period 1 (1789-1865)

par(mar=c(2,6,2,2))
sentence.list.sel=filter(sentence.list, Period==1)
for (i in 1:nrow(sentence.list.sel)) {
    sentence.list.sel$File[i] <- substr(sentence.list.sel$File[i], start = 6, stop = nchar(sentence.list.sel$File[i]) - 4)}
sentence.list.sel$File=factor(sentence.list.sel$File)
sentence.list.sel$FileOrdered=reorder(sentence.list.sel$File, 
                                  sentence.list.sel$word.count, 
                                  mean, 
                                  order=T)
beeswarm(word.count~FileOrdered, 
         data=sentence.list.sel,
         horizontal = TRUE, 
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.45, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.sel$FileOrdered),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Speeches during Period 1")

What are these short sentences?

sentence.list%>%
  filter(Period == 1, word.count<=3)%>%
  select(sentences)

Period 2 (1866-1945)

par(mar=c(2,6,2,2))
sentence.list.sel=filter(sentence.list, Period==2)
for (i in 1:nrow(sentence.list.sel)) {
    sentence.list.sel$File[i] <- substr(sentence.list.sel$File[i], start = 6, stop = nchar(sentence.list.sel$File[i]) - 4)}
sentence.list.sel$File=factor(sentence.list.sel$File)
sentence.list.sel$FileOrdered=reorder(sentence.list.sel$File, 
                                  sentence.list.sel$word.count, 
                                  mean, 
                                  order=T)
beeswarm(word.count~FileOrdered, 
         data=sentence.list.sel,
         horizontal = TRUE, 
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.45, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.sel$FileOrdered),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Speeches during Period 2")

What are these short sentences?

sentence.list%>%
  filter(Period == 2, word.count<=3)%>%
  select(sentences)

Period 3 (1946-2017)

par(mar=c(2,6,2,2))
sentence.list.sel=filter(sentence.list, Period==3)
for (i in 1:nrow(sentence.list.sel)) {
    sentence.list.sel$File[i] <- substr(sentence.list.sel$File[i], start = 6, stop = nchar(sentence.list.sel$File[i]) - 4)}
sentence.list.sel$File=factor(sentence.list.sel$File)
sentence.list.sel$FileOrdered=reorder(sentence.list.sel$File, sentence.list.sel$word.count, mean, order=T)
beeswarm(word.count~FileOrdered, 
         data=sentence.list.sel,
         horizontal = TRUE, 
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.45, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.sel$FileOrdered),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Speeches during Period 3")

What are these short sentences?

sentence.list%>%
  filter(Period == 3, word.count<=3)%>%
  select(sentences)

The three plots above show that the length of sentences in presendents’ inaugrual speeches has become shorter and shorter.

In Period 1, the largest number of words in a sentence is above 120, and some sentences has more than 80 words. Most sentences has words less than 60.

In Period 2, the largest number of words in a sentence is above 100, and some sentences has more than 60 words. Most sentences has words less than 40.

In Period 3, the largest number of words in a sentence is below 100, and some sentences has more than 40 words. Most sentences has words less than 30.

The pattern that the length of sentences in presendents’ inaugrual speeches has become shorter and shorter is consistent with the change of human’s expressing behavior.

Nowadays, people prefer to express themselves in an easier way to make their ideas clear rather than use long sentences with difficult structures.

Part II: Change in Emotions of Speakers

I continue my research with sentiment changes of speakers. In this part, I also use one sentence as a unit.

Data Analysis — Length of Sentences with Sentiment Analysis

First, I want to make a further study on sentence length variation over the course of the speech, with emotions. This is a combination of sentiment change and sentence length change.

Here I use the same color theme as in the movie “Inside Out.”

image

image

(Unfortunately, I cannot find the image of color theme!)

par(mfrow=c(3,1), mar=c(1,0,2,0), bty="n", xaxt="n", yaxt="n", font.main=1)
f.plotsent.len1(In.list=sentence.list, InPeriod = 1)
f.plotsent.len1(In.list=sentence.list, InPeriod = 2)
f.plotsent.len1(In.list=sentence.list, InPeriod = 3)

Due to the miss of details about color theme used here, the following analysis is subjective.

It makes sense that darker colors represent more intense emotions. And we often use reds to express anger, blues to express calm according to the psychology of color.

Here, I do not analyze these colors in detail, just make a demonstrate on the whole trend which these colorful plots show.

From the above pictures we can feel that the colors are becoming lighter and lighter from Period 1 to Period 3, which means that speakers’ emotions are becoming calmer and calmer.

This change is rational because people now can control their emotions better than before. In addition, the following presidents may gain some experience about how to express their emotions in speeches from the previous president. Therefore, they can express themselves in a less radical way.

Moreover, these plots also show the pattern that the length of sentences in speeches is becoming shorter and shorter.

Data Analysis — Clustering of Emotions

Next, I will show a more detailed study on emotion change of speakers among three different periods.

First, I give the heatmaps of speaker’s emotions in these three periods.

heatmap.2(cor(sentence.list%>%filter(Period==1)%>%select(anger:trust)), 
          scale = "none", cexRow = 0.8, cexCol = 0.8,
          col = bluered(100),  margin=c(6, 6), key=F,
          trace = "none", density.info = "none")

heatmap.2(cor(sentence.list%>%filter(Period==2)%>%select(anger:trust)), 
          scale = "none", cexRow = 0.8, cexCol = 0.8,
          col = bluered(100),  margin=c(6, 6), key=F,
          trace = "none", density.info = "none")

heatmap.2(cor(sentence.list%>%filter(Period==3)%>%select(anger:trust)), 
          scale = "none", cexRow = 0.8, cexCol = 0.8,
          col = bluered(100),  margin=c(6, 6), key=F,
          trace = "none", density.info = "none")

In my opinion, the extend of darkness represent the degree of correlation between two emotions.
Therefore, I think the correlation between positive emotions bocome higher and the correlation between negative emotions bocome lower than before, which means presidents now express more positive emotions than before.

The following plots give us a straight view of the distributions of emotions in these three periods.

par(mfrow=c(1,3))#, mar=c(1,0,2,0), bty="n", xaxt="n", yaxt="n", font.main=1)
emo.means=colMeans(sentence.list%>%filter(Period==1)%>%select(anger:trust)>0.01)
col.use=c("red2", "darkgoldenrod1", 
            "chartreuse3", "blueviolet",
            "darkgoldenrod2", "dodgerblue3", 
            "darkgoldenrod1", "darkgoldenrod1")
barplot(emo.means[order(emo.means)], las=2, col=col.use[order(emo.means)], horiz=T, main="Period 1")
emo.means=colMeans(sentence.list%>%filter(Period==2)%>%select(anger:trust)>0.01)
col.use=c("red2", "darkgoldenrod1", 
            "chartreuse3", "blueviolet",
            "darkgoldenrod2", "dodgerblue3", 
            "darkgoldenrod1", "darkgoldenrod1")
barplot(emo.means[order(emo.means)], las=2, col=col.use[order(emo.means)], horiz=T, main="Period 2")
emo.means=colMeans(sentence.list%>%filter(Period==3)%>%select(anger:trust)>0.01)
col.use=c("red2", "darkgoldenrod1", 
            "chartreuse3", "blueviolet",
            "darkgoldenrod2", "dodgerblue3", 
            "darkgoldenrod1", "darkgoldenrod1")
barplot(emo.means[order(emo.means)], las=2, col=col.use[order(emo.means)], horiz=T, main="Period 3")

From these plots we can see that in Period 1, fear is in the third place of the emotion expression. However, in Period 2, joy become the third place of the emotion expression. In addition, the negative emotions like disgust, sadness and anger have a less weight than before.

Thus, I will say that presidents today express more positive emotions than before and this change is also reasonable.

The following plot illustrates my view clearly.

period.summary=tbl_df(sentence.list)%>%
  group_by(Period)%>%
  summarise(
    negative=mean(negative),
    positive=mean(positive)
  )
ggplot(period.summary) +
  geom_point(mapping = aes(x = Period, y = negative, color = "negative")) +
  geom_line(mapping = aes(x = Period, y = negative, color = "negative")) +
  geom_point(mapping = aes(x = Period, y = positive, color = "positive")) +
  geom_line(mapping = aes(x = Period, y = positive, color = "positive")) +
  labs(y = "Attitude")

From this plot we can see that presidents always express more positive attitude than negative. And, there is a trend that they express more positive and less negative attitude than before.

Part III: Change in Topics of Presidents’ Inaugrual Speeches

Data Collection and Processing

For topic modeling, I still use one sentence as a unit. I prepare a corpus of sentence snippets as follows. For each speech, I start with sentences and prepare a snippet with a given sentence with the flanking sentences.

corpus.list=sentence.list[2:(nrow(sentence.list)-1), ]
sentence.pre=sentence.list$sentences[1:(nrow(sentence.list)-2)]
sentence.post=sentence.list$sentences[3:(nrow(sentence.list)-1)]
corpus.list$snippets=paste(sentence.pre, corpus.list$sentences, sentence.post, sep=" ")
rm.rows=(1:nrow(corpus.list))[corpus.list$sent.id==1]
rm.rows=c(rm.rows, rm.rows-1)
corpus.list=corpus.list[-rm.rows, ]

# Text mining
docs <- Corpus(VectorSource(corpus.list$snippsets))

#Text basic processing
#remove potentially problematic symbols
docs <-tm_map(docs,content_transformer(tolower))

#remove punctuation
docs <- tm_map(docs, removePunctuation)

#Strip digits
docs <- tm_map(docs, removeNumbers)

#remove stopwords
docs <- tm_map(docs, removeWords, stopwords("english"))

#remove whitespace
docs <- tm_map(docs, stripWhitespace)

#Stem document
docs <- tm_map(docs,stemDocument)

Data Analysis — Topic Modeling

Step 1: Gengerate document-term matrices.

dtm <- DocumentTermMatrix(docs)
#convert rownames to filenames 
for (i in 1:nrow(corpus.list)) {
    corpus.list$File[i] <- substr(corpus.list$File[i], start = 6, stop = nchar(corpus.list$File[i]) - 4)}
rownames(dtm) <- paste(corpus.list$File, corpus.list$sent.id, sep="_")

rowTotals <- apply(dtm , 1, sum) #Find the sum of words in each Document

dtm  <- dtm[rowTotals> 0, ]
corpus.list=corpus.list[rowTotals>0, ]

Step 2: Run LDA with 10 topics

The following table shows the number of sentences in each topic.

#Set parameters for Gibbs sampling
burnin <- 4000
iter <- 2000
thin <- 500
seed <-list(2003,5,63,100001,765)
nstart <- 5
best <- TRUE
#Number of topics
k <- 10
#Run LDA using Gibbs sampling
ldaOut <-LDA(dtm, k, method="Gibbs", control=list(nstart=nstart, 
                                                 seed = seed, best=best,
                                                 burnin = burnin, iter = iter, 
                                                 thin=thin))

I also give the top 20 most popular words in each topic.

ldaOut.terms
      Topic 1         Topic 2     Topic 3     Topic 4     Topic 5    Topic 6   Topic 7   
 [1,] "countri"       "nation"    "govern"    "public"    "time"     "shall"   "world"   
 [2,] "great"         "war"       "state"     "use"       "year"     "peopl"   "new"     
 [3,] "interest"      "peac"      "power"     "industri"  "now"      "may"     "america" 
 [4,] "everi"         "great"     "right"     "mean"      "man"      "duti"    "american"
 [5,] "mani"          "unit"      "constitut" "interest"  "come"     "upon"    "work"    
 [6,] "much"          "polici"    "union"     "secur"     "day"      "faith"   "let"     
 [7,] "present"       "forc"      "preserv"   "revenu"    "first"    "purpos"  "live"    
 [8,] "danger"        "foreign"   "within"    "product"   "histori"  "offic"   "nation"  
 [9,] "spirit"        "made"      "general"   "condit"    "futur"    "best"    "peac"    
[10,] "caus"          "secur"     "unit"      "busi"      "god"      "support" "seek"    
[11,] "patriot"       "maintain"  "protect"   "may"       "presid"   "confid"  "hope"    
[12,] "experi"        "less"      "principl"  "demand"    "stand"    "public"  "way"     
[13,] "success"       "establish" "author"    "need"      "today"    "servic"  "help"    
[14,] "continu"       "relat"     "form"      "well"      "generat"  "will"    "togeth"  
[15,] "happi"         "countri"   "equal"     "econom"    "heart"    "respons" "old"     
[16,] "mind"          "progress"  "feder"     "encourag"  "still"    "trust"   "land"    
[17,] "charact"       "intern"    "object"    "economi"   "last"     "honor"   "see"     
[18,] "fellowcitizen" "extend"    "whole"     "necessari" "american" "take"    "make"    
[19,] "result"        "state"     "citizen"   "labor"     "face"     "execut"  "promis"  
[20,] "exist"         "defens"    "limit"     "trade"     "past"     "oblig"   "strength"
      Topic 8     Topic 9     Topic 10   
 [1,] "law"       "will"      "peopl"    
 [2,] "upon"      "can"       "freedom"  
 [3,] "congress"  "must"      "free"     
 [4,] "parti"     "one"       "life"     
 [5,] "question"  "nation"    "liberti"  
 [6,] "polit"     "everi"     "human"    
 [7,] "effect"    "good"      "men"      
 [8,] "subject"   "make"      "justic"   
 [9,] "opinion"   "citizen"   "believ"   
[10,] "execut"    "never"     "thing"    
[11,] "legisl"    "like"      "civil"    
[12,] "administr" "other"     "long"     
[13,] "elect"     "need"      "republ"   
[14,] "control"   "anoth"     "know"     
[15,] "reason"    "communiti" "order"    
[16,] "given"     "race"      "democraci"
[17,] "enforc"    "done"      "common"   
[18,] "certain"   "noth"      "spirit"   
[19,] "action"    "whether"   "moral"    
[20,] "made"      "among"     "fear"     

Based on the most popular terms and the most salient terms for each topic, I assign a hashtag to each topic. This part is subjective because I set up these topics manually.

topics.hash=c("Govern", "Economy" , "Responsibility", "Peace", "Unity", "Freedom", "Defense", "Reformation", "Belief", "Patriotism") 
corpus.list$ldatopic=as.vector(ldaOut.topics)
corpus.list$ldahash=topics.hash[ldaOut.topics]
colnames(topicProbabilities)=topics.hash
corpus.list.df=cbind(corpus.list, topicProbabilities)

Frequencies of topics in different periods.

The following pie plots show the distributions of the topics of speeches in these three periods.

topic.1 <- corpus.list$ldatopic[corpus.list$Period == 1]
topic.prop.1 <- as.integer(table(topic.1))/length(topic.1)
per1 <- round(topic.prop.1 * 100, 2)
topic.per.1  <- paste(per1, "%", sep="")
period1 <- data.frame(Percentage =topic.prop.1, Topic = topics.hash, Percent=topic.per.1)
topic.2 <- corpus.list$ldatopic[corpus.list$Period == 2]
topic.prop.2 <- as.integer(table(topic.2))/length(topic.2)
per2 <- round(topic.prop.2 * 100, 2)
topic.per.2  <- paste(per2, "%", sep="")
period2 <- data.frame(Percentage =topic.prop.2, Topic = topics.hash, Percent=topic.per.2)
topic.3 <- corpus.list$ldatopic[corpus.list$Period == 3]
topic.prop.3 <- as.integer(table(topic.3))/length(topic.3)
per3 <- round(topic.prop.3 * 100, 2)
topic.per.3  <- paste(per3, "%", sep="")
period3 <- data.frame(Percentage =topic.prop.3, Topic = topics.hash, Percent=topic.per.3)
par(mfrow=c(1,3))
# Plot the chart.
pie(topic.prop.1, labels = topic.per.1, col = rainbow(length(topic.per.1)), main = "Topic Distribution in Period 1")
legend("topright", topics.hash, cex = 0.8, fill = rainbow(length(topic.per.1)))
pie(topic.prop.2, labels = topic.per.2, col = rainbow(length(topic.per.2)), main = "Topic Distribution in Period 2")
legend("topright", topics.hash, cex = 0.8, fill = rainbow(length(topic.per.2)))
pie(topic.prop.3, labels = topic.per.3, col = rainbow(length(topic.per.3)), main = "Topic Distribution in Period 3")
legend("topright", topics.hash, cex = 0.8, fill = rainbow(length(topic.per.3)))

From the plots, we know that Responsibility and Govern play important roles in Period 1, Peace and Denfense play important roles in both Period 2 and Period 3. However, Peace and Denfense cover over 2/3 topic in Period 3.

I think this change of topics is also consistent with the development of our society, since people care more about living a peaceful life now.

Conclusion:

From my study, I will draw a conclusion that the trend of presidents’ speeches from 1789 to 2017 correspond with the development of our human behaviours.

  1. Sentences become shorter than before, which implies that people are pursuing an simpler way to express themselves.

  2. Less radical in sentiment means people now can control their emotion well and can always keep calm. In addition, people now become more possitive than before.

  3. Topic change of speeches reflects our thoughts. It shows what kind of life we are living in or we want to live in.

Appendix: Word Cloud

In the end, I want to show the word clouds of speeches in three different periods.
(This is not part of my story, I just do this for fun.)

Data Collection and Processing

Step 0: Install and load libraries

packages.used=c("tm", "wordcloud", "RColorBrewer", 
                "dplyr", "tydytext")

# check packages that need to be installed.
packages.needed=setdiff(packages.used, 
                        intersect(installed.packages()[,1], 
                                  packages.used))
# install additional packages
if(length(packages.needed)>0){
  install.packages(packages.needed, dependencies = TRUE,
                   repos='http://cran.us.r-project.org')
}

library(tm)
library(wordcloud)
library(RColorBrewer)
library(dplyr)
library(tidytext)

Step 1: Read in the speeches

speeches=list.files(path = folder.path, pattern = "*.txt")
prex.out=substr(speeches, 6, nchar(speeches)-4)

ff.all.o<-Corpus(DirSource(folder.path))

Step 2: Text processing

ord <- as.factor(speech.list$File)
levels(ord) <- 1:58
ff.all <- ff.all.o[as.integer(ord)]
ff.all<-tm_map(ff.all, stripWhitespace)
ff.all<-tm_map(ff.all, content_transformer(tolower))
ff.all<-tm_map(ff.all, removeWords, stopwords("english"))
ff.all<-tm_map(ff.all, removeWords, character(0))
ff.all<-tm_map(ff.all, removePunctuation)

ff.1 <- ff.all[1:20]
ff.2 <- ff.all[21:40]
ff.3 <- ff.all[41:58]

tdm.1<-TermDocumentMatrix(ff.1)
tdm.2<-TermDocumentMatrix(ff.2)
tdm.3<-TermDocumentMatrix(ff.3)

tdm.tidy.1=tidy(tdm.1)
tdm.tidy.2=tidy(tdm.2)
tdm.tidy.3=tidy(tdm.3)

tdm.overall.1=summarise(group_by(tdm.tidy.1, term), sum(count))
tdm.overall.2=summarise(group_by(tdm.tidy.2, term), sum(count))
tdm.overall.3=summarise(group_by(tdm.tidy.3, term), sum(count))

Data Analysis — Wordclouds

Make wordclouds of speeches in three different periods using TF-IDF weighted document-term matrices.

As I would like to identify interesting words for speeches in each period, I use TF-IDF to weigh each term within speeches in each period. It highlights terms that are more widely-used in a particular period.

dtm.1 <- DocumentTermMatrix(ff.1,
                          control = list(weighting = function(x)
                                             weightTfIdf(x, 
                                                         normalize =FALSE),
                                         stopwords = TRUE))
ff.dtm.1=tidy(dtm.1)
dtm.2 <- DocumentTermMatrix(ff.2,
                          control = list(weighting = function(x)
                                             weightTfIdf(x, 
                                                         normalize =FALSE),
                                         stopwords = TRUE))
ff.dtm.2=tidy(dtm.2)
dtm.3 <- DocumentTermMatrix(ff.3,
                          control = list(weighting = function(x)
                                             weightTfIdf(x, 
                                                         normalize =FALSE),
                                         stopwords = TRUE))
ff.dtm.3=tidy(dtm.3)
par(mfrow=c(1,3),mar=c(1,1,1,1))
wordcloud(ff.dtm.1$term, ff.dtm.1$count,
          scale=c(5,0.5),
          max.words=100,
          min.freq=1,
          random.order=FALSE,
          rot.per=0.3,
          use.r.layout=T,
          random.color=FALSE,
          colors=brewer.pal(9,"Blues"))
text(0.5,-0.1,"Period 1",col="black",cex=1.2)
wordcloud(ff.dtm.2$term, ff.dtm.2$count,
          scale=c(5,0.5),
          max.words=100,
          min.freq=1,
          random.order=FALSE,
          rot.per=0.3,
          use.r.layout=T,
          random.color=FALSE,
          colors=brewer.pal(9,"Reds"))
text(0.5,-0.1,"Period 2",col="black",cex=1.2)
wordcloud(ff.dtm.3$term, ff.dtm.3$count,
          scale=c(5,0.5),
          max.words=100,
          min.freq=1,
          random.order=FALSE,
          rot.per=0.3,
          use.r.layout=T,
          random.color=FALSE,
          colors=brewer.pal(9,"Greens"))
text(0.5,-0.1,"Period 3",col="black",cex=1.2)

LS0tCnRpdGxlOiAiV2hhdCBpcyB0aGUgdHJlbmQgb2YgVS5TLiBwcmVzaWRlbnRzJyBpbmF1Z3J1YWwgc3BlZWNoZXM/IgphdXRob3I6ICJYaWFveGlhbyBHdW87IHhnMjI4MiIKZGF0ZTogIkphbiAyOCwgMjAxOCIKb3V0cHV0OgogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgoqKjxmb250IHNpemU9NT5EYXRhIERlc2NyaXB0aW9uPC9mb250PioqICAKClRoZSBkYXRhIGNvbXByaXNlcyBvZiA1OCBpbmF1Z3J1YWwgc3BlZWNoZXMsIGZyb20gdGhhdCBvZiBHZW9yZ2UgV2FzaGluZ3RvbiB0byB0aGF0IG9mIERvbmFsZCBUcnVtcCB3aGljaCB3YXMgZGVsaXZlcmVkIGVhcmxpZXIgdGhpcyB5ZWFyLgoKKio8Zm9udCBzaXplPTU+UmVzZWFyY2ggUXVlc3Rpb248L2ZvbnQ+KiogIAoKRmlyc3Qgb2YgYWxsLCBJIG11c3QgYWRtaXQgdGhhdCBJIGFtIG5vdCBnb29kIGF0IHBvbGl0aWNzLCBzbyBJIGNob29zZSB0byB0ZWxsIG15IHN0b3J5IGp1c3QgZnJvbSB0aGUgZGF0YSBpdHNlbGYgYW5kIGRvIG5vdCBtYWtlIGFueSBjb21tZW50IG9uIHBvbGl0aWNzLgoKVGhlIG1haW4gcXVlc3Rpb24gb2YgbXkgcmVzZWFyY2ggaXMgdG8gYW5hbHlzZSB0aGUgdHJlbmQgb2YgcHJlc2lkZW50cycgaW5hdWdydWFsIHNwZWVjaGVzIGFjY29yZGluZyB0byB0aGUgNTggaW5hdWdydWFsIHNwZWVjaGVzIHdlIGhhdmUgZnJvbSAxNzg5LTIwMTcuIFNwZWNpZmljYWxseSwgSSB3YW50IHRvIHRlbGwgYSBzdG9yeSBmcm9tIHRoZSBmb2xsb3dpbmcgdGhyZWUgYXNwZWN0czoKCjEuIENoYW5nZSBpbiBsZW5ndGggb2Ygc2VudGVuY2VzIGluIHByZXNpZGVudHMnIGluYXVncnVhbCBzcGVlY2hlcwoyLiBDaGFuZ2UgaW4gc3BlYWtlcnMnIGVtb3Rpb25zIHdpdGggcHJlc2lkZW50cycgaW5hdWdydWFsIHNwZWVjaGVzCjMuIENoYW5nZSBpbiB0b3BpY3Mgb2YgcHJlc2lkZW50cycgaW5hdWdydWFsIHNwZWVjaGVzCgpJbiBvcmRlciB0byBhbmFseXNlIHRoZXNlIGNoYW5nZXMgb2YgcHJlc2lkZW50cycgaW5hdWdydWFsIHNwZWVjaGVzIGluIHRoZXNlIHllYXJzLCBJIHNwbGl0IHRoZSBkYXRhIGludG8gdGhyZWUgcGFydHMgYWNjb3JkaW5nIHRvIHRoZSBkYXRlIG9mIHRoZXNlIHNwZWVjaGVzOiAgClBlcmlvZCAxOiAxNzg5LTE4NjUsIEdlb3JnZSBXYXNoaW5ndG9uLUFicmFoYW0gTGluY29sbiAgClBlcmlvZCAyOiAxODY2LTE5NDUsIFVseXNzZXMgUy4gR3JhbnQtRnJhbmtsaW4gRC4gUm9vc2V2ZWx0ICAKUGVyaW9kIDM6IDE5NDYtMjAxNywgSGFycnkgUy4gVHJ1bWFuLURvbmFsZCBKLiBUcnVtcAoKSW4gdGhpcyByZXBvcnQsIEkgd2lsbCBmb2N1cyBteSBzdHVkeSBvbiBjaGFuZ2VzIGFtb25nIHNwZWVjaGVzIG9mIHRoZXNlIHRocmVlIHBlcmlvZHMgYW5kIHRlbGwgbXkgb3duIHN0b3J5LgoKIyMgUGFydCBJOiBDaGFuZ2UgaW4gTGVuZ3RoIG9mIFNlbnRlbmNlcwoKKipGaXJzdCwgSSBsb29rIGF0IHRoZSBjaGFuZ2UgaW4gbGVuZ3RoIG9mIHNlbnRlbmNlcyBvZiBwcmVzaWRlbnRzJyBpbmF1Z3J1YWwgc3BlZWNoZXMuKioKCiMjIyBEYXRhIENvbGxlY3Rpb24gYW5kIFByb2Nlc3NpbmcKClN0ZXAgMDogQ2hlY2sgYW5kIGluc3RhbGwgbmVlZGVkIHBhY2thZ2VzLiBMb2FkIHRoZSBsaWJyYXJpZXMgYW5kIGZ1bmN0aW9ucy4KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBhY2thZ2VzLnVzZWQgPSBjKCJydmVzdCIsICJ0aWJibGUiLCAicWRhcCIsInNlbnRpbWVudHIiLCAiZ3Bsb3RzIiwgImRwbHlyIiwgInRtIiwgInN5dXpoZXQiLCAiZmFjdG9leHRyYSIsICJiZWVzd2FybSIsICJzY2FsZXMiLCAiUkNvbG9yQnJld2VyIiwgIlJBTk4iLCAidG0iLCAidG9waWNtb2RlbHMiKQoKIyBjaGVjayBwYWNrYWdlcyB0aGF0IG5lZWQgdG8gYmUgaW5zdGFsbGVkLgpwYWNrYWdlcy5uZWVkZWQ9c2V0ZGlmZihwYWNrYWdlcy51c2VkLCAKICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJzZWN0KGluc3RhbGxlZC5wYWNrYWdlcygpWywxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrYWdlcy51c2VkKSkKIyBpbnN0YWxsIGFkZGl0aW9uYWwgcGFja2FnZXMKaWYobGVuZ3RoKHBhY2thZ2VzLm5lZWRlZCk+MCl7CiAgaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlcy5uZWVkZWQsIGRlcGVuZGVuY2llcyA9IFRSVUUpCn0KCiMgbG9hZCBwYWNrYWdlcwpsaWJyYXJ5KCJydmVzdCIpCmxpYnJhcnkoInRpYmJsZSIpCmxpYnJhcnkoInFkYXAiKQpsaWJyYXJ5KCJzZW50aW1lbnRyIikKbGlicmFyeSgiZ3Bsb3RzIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJ0bSIpCmxpYnJhcnkoInN5dXpoZXQiKQpsaWJyYXJ5KCJmYWN0b2V4dHJhIikKbGlicmFyeSgiYmVlc3dhcm0iKQpsaWJyYXJ5KCJzY2FsZXMiKQpsaWJyYXJ5KCJSQ29sb3JCcmV3ZXIiKQpsaWJyYXJ5KCJSQU5OIikKbGlicmFyeSgidG0iKQpsaWJyYXJ5KCJ0b3BpY21vZGVscyIpCgpzb3VyY2UoIn4vRGVza3RvcC9DVV9TdGF0cy8yMDE4IFNwcmluZy9HUjUyNDMgQURTL1Byb2plY3QgMS93azItVGV4dE1pbmluZy9saWIvcGxvdHN0YWNrZWQuUiIpCnNvdXJjZSgifi9EZXNrdG9wL0NVX1N0YXRzLzIwMTggU3ByaW5nL0dSNTI0MyBBRFMvUHJvamVjdCAxL3drMi1UZXh0TWluaW5nL2xpYi9zcGVlY2hGdW5jcy5SIikKYGBgCgpTdGVwIDE6IFJlYWQgaW4gdGhlIHNwZWVjaGVzCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KCJ3b3JkY2xvdWQiKQpsaWJyYXJ5KCJ0aWR5dGV4dCIpCmxpYnJhcnkoInJlYWR4bCIpCgpzcGVlY2gubGlzdCA8LSByZWFkX3hsc3goIn4vRGVza3RvcC9DVV9TdGF0cy8yMDE4IFNwcmluZy9HUjUyNDMgQURTL1Byb2plY3QgMS9kYXRhL0luYXVndXJhdGlvbkluZm8ueGxzeCIpCnNwZWVjaC5saXN0JEZpbGUgPC0gcGFzdGUoc3BlZWNoLmxpc3QkRmlsZSwgc3BlZWNoLmxpc3QkVGVybSwgc2VwID0gIi0iKQpzcGVlY2gubGlzdCRGaWxlPC0gcGFzdGUoImluYXVnIiwgc3BlZWNoLmxpc3QkRmlsZSwgIi50eHQiLCBzZXAgPSAiIikKCnNwZWVjaC5saXN0JFBlcmlvZCA8LSByZXAoMTozLCBjKDIwLCAyMCwgMTgpKQoKZm9sZGVyLnBhdGg9In4vRGVza3RvcC9DVV9TdGF0cy8yMDE4IFNwcmluZy9HUjUyNDMgQURTL1Byb2plY3QgMS9kYXRhL0luYXVndXJhbFNwZWVjaGVzLyIKc3BlZWNoZXM9bGlzdC5maWxlcyhwYXRoID0gZm9sZGVyLnBhdGgsIHBhdHRlcm4gPSAiKi50eHQiKQoKdGVtcCA8LSBsaXN0LmZpbGVzKHBhdGggPSBmb2xkZXIucGF0aCwgcGF0dGVybj0iKi50eHQiKQpzcGVlY2gubGlzdCRmdWxsdGV4dCA8LSBOQQpmb3IoaSBpbiAxOmxlbmd0aCh0ZW1wKSl7CnNwZWVjaC5saXN0JGZ1bGx0ZXh0W2ldPC1wYXN0ZShyZWFkTGluZXMocGFzdGUoZm9sZGVyLnBhdGgsc3BlZWNoLmxpc3QkRmlsZVtpXSwgc2VwID0gIiIpKSwgY29sbGFwc2UgPSAiICIpCn0KYGBgCgpTdGVwIDI6IEdlbmVyYXRlIGxpc3Qgb2Ygc2VudGVuY2VzCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpzZW50ZW5jZS5saXN0PU5VTEwKZm9yKGkgaW4gMTpucm93KHNwZWVjaC5saXN0KSl7CiAgc2VudGVuY2VzPXNlbnRfZGV0ZWN0KHNwZWVjaC5saXN0JGZ1bGx0ZXh0W2ldLAogICAgICAgICAgICAgICAgICAgICAgICBlbmRtYXJrcyA9IGMoIj8iLCAiLiIsICIhIiwgInwiLCI7IikpCiAgaWYobGVuZ3RoKHNlbnRlbmNlcyk+MCl7CiAgICBlbW90aW9ucz1nZXRfbnJjX3NlbnRpbWVudChzZW50ZW5jZXMpCiAgICB3b3JkLmNvdW50PXdvcmRfY291bnQoc2VudGVuY2VzKQogICAgIyBjb2xuYW1lcyhlbW90aW9ucyk9cGFzdGUwKCJlbW8uIiwgY29sbmFtZXMoZW1vdGlvbnMpKQogICAgIyBpbiBjYXNlIHRoZSB3b3JkIGNvdW50cyBhcmUgemVyb3M/CiAgICBlbW90aW9ucz1kaWFnKDEvKHdvcmQuY291bnQrMC4wMSkpJSolYXMubWF0cml4KGVtb3Rpb25zKQogICAgc2VudGVuY2UubGlzdD1yYmluZChzZW50ZW5jZS5saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgY2JpbmQoc3BlZWNoLmxpc3RbaSwtbmNvbChzcGVlY2gubGlzdCldLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW50ZW5jZXM9YXMuY2hhcmFjdGVyKHNlbnRlbmNlcyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JkLmNvdW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbW90aW9ucywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VudC5pZD0xOmxlbmd0aChzZW50ZW5jZXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICkKICB9Cn0KCiMgU29tZSBub24tc2VudGVuY2VzIGV4aXN0IGluIHJhdyBkYXRhIGR1ZSB0byBlcnJvbmVvdXMgZXh0cmEgZW5kLW9mIHNlbnRlbmNlIG1hcmtzLiAKc2VudGVuY2UubGlzdD0KICBzZW50ZW5jZS5saXN0JT4lCiAgZmlsdGVyKCFpcy5uYSh3b3JkLmNvdW50KSkgCmBgYAoKIyMjIERhdGEgQW5hbHlzaXMgLS0tIExlbmd0aCBvZiBTZW50ZW5jZXMKCjxmb250IHNpemU9ND5PdmVydmlldyBvZiBzZW50ZW5jZSBsZW5ndGggZGlzdHJpYnV0aW9uIGJ5IGRpZmZlcmVudCB0aW1lIHBlcmlvZHMgb2Ygc3BlZWNoZXM8L2ZvbnQ+CgojIyMjIFBlcmlvZCAxICgxNzg5LTE4NjUpCmBgYHtyfQpwYXIobWFyPWMoMiw2LDIsMikpCgpzZW50ZW5jZS5saXN0LnNlbD1maWx0ZXIoc2VudGVuY2UubGlzdCwgUGVyaW9kPT0xKQoKZm9yIChpIGluIDE6bnJvdyhzZW50ZW5jZS5saXN0LnNlbCkpIHsKICAgIHNlbnRlbmNlLmxpc3Quc2VsJEZpbGVbaV0gPC0gc3Vic3RyKHNlbnRlbmNlLmxpc3Quc2VsJEZpbGVbaV0sIHN0YXJ0ID0gNiwgc3RvcCA9IG5jaGFyKHNlbnRlbmNlLmxpc3Quc2VsJEZpbGVbaV0pIC0gNCl9CgpzZW50ZW5jZS5saXN0LnNlbCRGaWxlPWZhY3RvcihzZW50ZW5jZS5saXN0LnNlbCRGaWxlKQoKc2VudGVuY2UubGlzdC5zZWwkRmlsZU9yZGVyZWQ9cmVvcmRlcihzZW50ZW5jZS5saXN0LnNlbCRGaWxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlLmxpc3Quc2VsJHdvcmQuY291bnQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcj1UKQoKYmVlc3dhcm0od29yZC5jb3VudH5GaWxlT3JkZXJlZCwgCiAgICAgICAgIGRhdGE9c2VudGVuY2UubGlzdC5zZWwsCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLCAKICAgICAgICAgcGNoPTE2LCBjb2w9YWxwaGEoYnJld2VyLnBhbCg5LCAiU2V0MSIpLCAwLjYpLCAKICAgICAgICAgY2V4PTAuNTUsIGNleC5heGlzPTAuNDUsIGNleC5sYWI9MC44LAogICAgICAgICBzcGFjaW5nPTUvbmxldmVscyhzZW50ZW5jZS5saXN0LnNlbCRGaWxlT3JkZXJlZCksCiAgICAgICAgIGxhcz0yLCB4bGFiPSJOdW1iZXIgb2Ygd29yZHMgaW4gYSBzZW50ZW5jZS4iLCB5bGFiPSIiLAogICAgICAgICBtYWluPSJTcGVlY2hlcyBkdXJpbmcgUGVyaW9kIDEiKQoKYGBgCgpXaGF0IGFyZSB0aGVzZSBzaG9ydCBzZW50ZW5jZXM/CmBgYHtyfQpzZW50ZW5jZS5saXN0JT4lCiAgZmlsdGVyKFBlcmlvZCA9PSAxLCB3b3JkLmNvdW50PD0zKSU+JQogIHNlbGVjdChzZW50ZW5jZXMpCmBgYAojIyMjIFBlcmlvZCAyICgxODY2LTE5NDUpCmBgYHtyfQoKcGFyKG1hcj1jKDIsNiwyLDIpKQoKc2VudGVuY2UubGlzdC5zZWw9ZmlsdGVyKHNlbnRlbmNlLmxpc3QsIFBlcmlvZD09MikKCmZvciAoaSBpbiAxOm5yb3coc2VudGVuY2UubGlzdC5zZWwpKSB7CiAgICBzZW50ZW5jZS5saXN0LnNlbCRGaWxlW2ldIDwtIHN1YnN0cihzZW50ZW5jZS5saXN0LnNlbCRGaWxlW2ldLCBzdGFydCA9IDYsIHN0b3AgPSBuY2hhcihzZW50ZW5jZS5saXN0LnNlbCRGaWxlW2ldKSAtIDQpfQoKc2VudGVuY2UubGlzdC5zZWwkRmlsZT1mYWN0b3Ioc2VudGVuY2UubGlzdC5zZWwkRmlsZSkKCnNlbnRlbmNlLmxpc3Quc2VsJEZpbGVPcmRlcmVkPXJlb3JkZXIoc2VudGVuY2UubGlzdC5zZWwkRmlsZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW50ZW5jZS5saXN0LnNlbCR3b3JkLmNvdW50LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXI9VCkKCmJlZXN3YXJtKHdvcmQuY291bnR+RmlsZU9yZGVyZWQsIAogICAgICAgICBkYXRhPXNlbnRlbmNlLmxpc3Quc2VsLAogICAgICAgICBob3Jpem9udGFsID0gVFJVRSwgCiAgICAgICAgIHBjaD0xNiwgY29sPWFscGhhKGJyZXdlci5wYWwoOSwgIlNldDEiKSwgMC42KSwgCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjQ1LCBjZXgubGFiPTAuOCwKICAgICAgICAgc3BhY2luZz01L25sZXZlbHMoc2VudGVuY2UubGlzdC5zZWwkRmlsZU9yZGVyZWQpLAogICAgICAgICBsYXM9MiwgeGxhYj0iTnVtYmVyIG9mIHdvcmRzIGluIGEgc2VudGVuY2UuIiwgeWxhYj0iIiwKICAgICAgICAgbWFpbj0iU3BlZWNoZXMgZHVyaW5nIFBlcmlvZCAyIikKCmBgYAoKV2hhdCBhcmUgdGhlc2Ugc2hvcnQgc2VudGVuY2VzPwpgYGB7cn0Kc2VudGVuY2UubGlzdCU+JQogIGZpbHRlcihQZXJpb2QgPT0gMiwgd29yZC5jb3VudDw9MyklPiUKICBzZWxlY3Qoc2VudGVuY2VzKQpgYGAKCiMjIyMgUGVyaW9kIDMgKDE5NDYtMjAxNykKYGBge3J9CnBhcihtYXI9YygyLDYsMiwyKSkKCnNlbnRlbmNlLmxpc3Quc2VsPWZpbHRlcihzZW50ZW5jZS5saXN0LCBQZXJpb2Q9PTMpCgpmb3IgKGkgaW4gMTpucm93KHNlbnRlbmNlLmxpc3Quc2VsKSkgewogICAgc2VudGVuY2UubGlzdC5zZWwkRmlsZVtpXSA8LSBzdWJzdHIoc2VudGVuY2UubGlzdC5zZWwkRmlsZVtpXSwgc3RhcnQgPSA2LCBzdG9wID0gbmNoYXIoc2VudGVuY2UubGlzdC5zZWwkRmlsZVtpXSkgLSA0KX0KCnNlbnRlbmNlLmxpc3Quc2VsJEZpbGU9ZmFjdG9yKHNlbnRlbmNlLmxpc3Quc2VsJEZpbGUpCgpzZW50ZW5jZS5saXN0LnNlbCRGaWxlT3JkZXJlZD1yZW9yZGVyKHNlbnRlbmNlLmxpc3Quc2VsJEZpbGUsIHNlbnRlbmNlLmxpc3Quc2VsJHdvcmQuY291bnQsIG1lYW4sIG9yZGVyPVQpCgpiZWVzd2FybSh3b3JkLmNvdW50fkZpbGVPcmRlcmVkLCAKICAgICAgICAgZGF0YT1zZW50ZW5jZS5saXN0LnNlbCwKICAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUsIAogICAgICAgICBwY2g9MTYsIGNvbD1hbHBoYShicmV3ZXIucGFsKDksICJTZXQxIiksIDAuNiksIAogICAgICAgICBjZXg9MC41NSwgY2V4LmF4aXM9MC40NSwgY2V4LmxhYj0wLjgsCiAgICAgICAgIHNwYWNpbmc9NS9ubGV2ZWxzKHNlbnRlbmNlLmxpc3Quc2VsJEZpbGVPcmRlcmVkKSwKICAgICAgICAgbGFzPTIsIHhsYWI9Ik51bWJlciBvZiB3b3JkcyBpbiBhIHNlbnRlbmNlLiIsIHlsYWI9IiIsCiAgICAgICAgIG1haW49IlNwZWVjaGVzIGR1cmluZyBQZXJpb2QgMyIpCgpgYGAKCldoYXQgYXJlIHRoZXNlIHNob3J0IHNlbnRlbmNlcz8KYGBge3J9CnNlbnRlbmNlLmxpc3QlPiUKICBmaWx0ZXIoUGVyaW9kID09IDMsIHdvcmQuY291bnQ8PTMpJT4lCiAgc2VsZWN0KHNlbnRlbmNlcykKYGBgCgoqKlRoZSB0aHJlZSBwbG90cyBhYm92ZSBzaG93IHRoYXQgdGhlIGxlbmd0aCBvZiBzZW50ZW5jZXMgaW4gcHJlc2VuZGVudHMnIGluYXVncnVhbCBzcGVlY2hlcyBoYXMgYmVjb21lIHNob3J0ZXIgYW5kIHNob3J0ZXIuKiogIAoKSW4gUGVyaW9kIDEsIHRoZSBsYXJnZXN0IG51bWJlciBvZiB3b3JkcyBpbiBhIHNlbnRlbmNlIGlzIGFib3ZlIDEyMCwgYW5kIHNvbWUgc2VudGVuY2VzIGhhcyBtb3JlIHRoYW4gODAgd29yZHMuIE1vc3Qgc2VudGVuY2VzIGhhcyB3b3JkcyBsZXNzIHRoYW4gNjAuICAKCkluIFBlcmlvZCAyLCB0aGUgbGFyZ2VzdCBudW1iZXIgb2Ygd29yZHMgaW4gYSBzZW50ZW5jZSBpcyBhYm92ZSAxMDAsIGFuZCBzb21lIHNlbnRlbmNlcyBoYXMgbW9yZSB0aGFuIDYwIHdvcmRzLiBNb3N0IHNlbnRlbmNlcyBoYXMgd29yZHMgbGVzcyB0aGFuIDQwLiAgCgpJbiBQZXJpb2QgMywgdGhlIGxhcmdlc3QgbnVtYmVyIG9mIHdvcmRzIGluIGEgc2VudGVuY2UgaXMgYmVsb3cgMTAwLCBhbmQgc29tZSBzZW50ZW5jZXMgaGFzIG1vcmUgdGhhbiA0MCB3b3Jkcy4gTW9zdCBzZW50ZW5jZXMgaGFzIHdvcmRzIGxlc3MgdGhhbiAzMC4KCioqVGhlIHBhdHRlcm4gdGhhdCB0aGUgbGVuZ3RoIG9mIHNlbnRlbmNlcyBpbiBwcmVzZW5kZW50cycgaW5hdWdydWFsIHNwZWVjaGVzIGhhcyBiZWNvbWUgc2hvcnRlciBhbmQgc2hvcnRlciBpcyBjb25zaXN0ZW50IHdpdGggdGhlIGNoYW5nZSBvZiBodW1hbidzIGV4cHJlc3NpbmcgYmVoYXZpb3IuKiogIAoKTm93YWRheXMsIHBlb3BsZSBwcmVmZXIgdG8gZXhwcmVzcyB0aGVtc2VsdmVzIGluIGFuIGVhc2llciB3YXkgdG8gbWFrZSB0aGVpciBpZGVhcyBjbGVhciByYXRoZXIgdGhhbiB1c2UgbG9uZyBzZW50ZW5jZXMgd2l0aCBkaWZmaWN1bHQgc3RydWN0dXJlcy4gCgoKIyMgUGFydCBJSTogQ2hhbmdlIGluIEVtb3Rpb25zIG9mIFNwZWFrZXJzCgoqKkkgY29udGludWUgbXkgcmVzZWFyY2ggd2l0aCBzZW50aW1lbnQgY2hhbmdlcyBvZiBzcGVha2Vycy4qKgpJbiB0aGlzIHBhcnQsIEkgYWxzbyB1c2Ugb25lIHNlbnRlbmNlIGFzIGEgdW5pdC4KCiMjIyBEYXRhIEFuYWx5c2lzIC0tLSBMZW5ndGggb2YgU2VudGVuY2VzIHdpdGggU2VudGltZW50IEFuYWx5c2lzCgpGaXJzdCwgSSB3YW50IHRvIG1ha2UgYSBmdXJ0aGVyIHN0dWR5IG9uIHNlbnRlbmNlIGxlbmd0aCB2YXJpYXRpb24gb3ZlciB0aGUgY291cnNlIG9mIHRoZSBzcGVlY2gsIHdpdGggZW1vdGlvbnMuIFRoaXMgaXMgYSBjb21iaW5hdGlvbiBvZiBzZW50aW1lbnQgY2hhbmdlIGFuZCBzZW50ZW5jZSBsZW5ndGggY2hhbmdlLgoKSGVyZSBJIHVzZSB0aGUgc2FtZSBjb2xvciB0aGVtZSBhcyBpbiB0aGUgbW92aWUgIkluc2lkZSBPdXQuIgoKIVtpbWFnZV0oaHR0cDovL3d3dy5zdGFmZm9yZHNjaG9vbHMubmV0L2Ntcy9saWIwMTEvVkEwMTgxODcyMy9DZW50cmljaXR5L0RvbWFpbi8zNTc0L2NoYXJhY3Rlcl9pY29uLnBuZykKCihVbmZvcnR1bmF0ZWx5LCBJIGNhbm5vdCBmaW5kIHRoZSBpbWFnZSBvZiBjb2xvciB0aGVtZSEpICAKCmBgYHtyfQpwYXIobWZyb3c9YygzLDEpLCBtYXI9YygxLDAsMiwwKSwgYnR5PSJuIiwgeGF4dD0ibiIsIHlheHQ9Im4iLCBmb250Lm1haW49MSkKCmYucGxvdHNlbnQubGVuMShJbi5saXN0PXNlbnRlbmNlLmxpc3QsIEluUGVyaW9kID0gMSkKZi5wbG90c2VudC5sZW4xKEluLmxpc3Q9c2VudGVuY2UubGlzdCwgSW5QZXJpb2QgPSAyKQpmLnBsb3RzZW50LmxlbjEoSW4ubGlzdD1zZW50ZW5jZS5saXN0LCBJblBlcmlvZCA9IDMpCgoKYGBgCkR1ZSB0byB0aGUgbWlzcyBvZiBkZXRhaWxzIGFib3V0IGNvbG9yIHRoZW1lIHVzZWQgaGVyZSwgdGhlIGZvbGxvd2luZyBhbmFseXNpcyBpcyBzdWJqZWN0aXZlLiAKCkl0IG1ha2VzIHNlbnNlIHRoYXQgZGFya2VyIGNvbG9ycyByZXByZXNlbnQgbW9yZSBpbnRlbnNlIGVtb3Rpb25zLiBBbmQgd2Ugb2Z0ZW4gdXNlIHJlZHMgdG8gZXhwcmVzcyBhbmdlciwgYmx1ZXMgdG8gZXhwcmVzcyBjYWxtIGFjY29yZGluZyB0byB0aGUgcHN5Y2hvbG9neSBvZiBjb2xvci4gCgoqKkhlcmUsIEkgZG8gbm90IGFuYWx5emUgdGhlc2UgY29sb3JzIGluIGRldGFpbCwganVzdCBtYWtlIGEgZGVtb25zdHJhdGUgb24gdGhlIHdob2xlIHRyZW5kIHdoaWNoIHRoZXNlIGNvbG9yZnVsIHBsb3RzIHNob3cuKioKCkZyb20gdGhlIGFib3ZlIHBpY3R1cmVzIHdlIGNhbiBmZWVsIHRoYXQgdGhlIGNvbG9ycyBhcmUgYmVjb21pbmcgbGlnaHRlciBhbmQgbGlnaHRlciBmcm9tIFBlcmlvZCAxIHRvIFBlcmlvZCAzLCB3aGljaCBtZWFucyB0aGF0IHNwZWFrZXJzJyBlbW90aW9ucyBhcmUgYmVjb21pbmcgY2FsbWVyIGFuZCBjYWxtZXIuCgoqKlRoaXMgY2hhbmdlIGlzIHJhdGlvbmFsIGJlY2F1c2UgcGVvcGxlIG5vdyBjYW4gY29udHJvbCB0aGVpciBlbW90aW9ucyBiZXR0ZXIgdGhhbiBiZWZvcmUuIEluIGFkZGl0aW9uLCB0aGUgZm9sbG93aW5nIHByZXNpZGVudHMgbWF5IGdhaW4gc29tZSBleHBlcmllbmNlIGFib3V0IGhvdyB0byBleHByZXNzIHRoZWlyIGVtb3Rpb25zIGluIHNwZWVjaGVzIGZyb20gdGhlIHByZXZpb3VzIHByZXNpZGVudC4gVGhlcmVmb3JlLCB0aGV5IGNhbiBleHByZXNzIHRoZW1zZWx2ZXMgaW4gYSBsZXNzIHJhZGljYWwgd2F5LioqCgpNb3Jlb3ZlciwgdGhlc2UgcGxvdHMgYWxzbyBzaG93IHRoZSBwYXR0ZXJuIHRoYXQgdGhlIGxlbmd0aCBvZiBzZW50ZW5jZXMgaW4gc3BlZWNoZXMgaXMgYmVjb21pbmcgc2hvcnRlciBhbmQgc2hvcnRlci4KCiMjIyBEYXRhIEFuYWx5c2lzIC0tLSBDbHVzdGVyaW5nIG9mIEVtb3Rpb25zCk5leHQsIEkgd2lsbCBzaG93IGEgbW9yZSBkZXRhaWxlZCBzdHVkeSBvbiBlbW90aW9uIGNoYW5nZSBvZiBzcGVha2VycyBhbW9uZyB0aHJlZSBkaWZmZXJlbnQgcGVyaW9kcy4KCkZpcnN0LCBJIGdpdmUgdGhlIGhlYXRtYXBzIG9mIHNwZWFrZXIncyBlbW90aW9ucyBpbiB0aGVzZSB0aHJlZSBwZXJpb2RzLgpgYGB7cixmaWcud2lkdGg9MS40LCBmaWcuaGVpZ2h0PTEuNH0KCmhlYXRtYXAuMihjb3Ioc2VudGVuY2UubGlzdCU+JWZpbHRlcihQZXJpb2Q9PTEpJT4lc2VsZWN0KGFuZ2VyOnRydXN0KSksIAogICAgICAgICAgc2NhbGUgPSAibm9uZSIsIGNleFJvdyA9IDAuOCwgY2V4Q29sID0gMC44LAogICAgICAgICAgY29sID0gYmx1ZXJlZCgxMDApLCAgbWFyZ2luPWMoNiwgNiksIGtleT1GLAogICAgICAgICAgdHJhY2UgPSAibm9uZSIsIGRlbnNpdHkuaW5mbyA9ICJub25lIikKaGVhdG1hcC4yKGNvcihzZW50ZW5jZS5saXN0JT4lZmlsdGVyKFBlcmlvZD09MiklPiVzZWxlY3QoYW5nZXI6dHJ1c3QpKSwgCiAgICAgICAgICBzY2FsZSA9ICJub25lIiwgY2V4Um93ID0gMC44LCBjZXhDb2wgPSAwLjgsCiAgICAgICAgICBjb2wgPSBibHVlcmVkKDEwMCksICBtYXJnaW49Yyg2LCA2KSwga2V5PUYsCiAgICAgICAgICB0cmFjZSA9ICJub25lIiwgZGVuc2l0eS5pbmZvID0gIm5vbmUiKQpoZWF0bWFwLjIoY29yKHNlbnRlbmNlLmxpc3QlPiVmaWx0ZXIoUGVyaW9kPT0zKSU+JXNlbGVjdChhbmdlcjp0cnVzdCkpLCAKICAgICAgICAgIHNjYWxlID0gIm5vbmUiLCBjZXhSb3cgPSAwLjgsIGNleENvbCA9IDAuOCwKICAgICAgICAgIGNvbCA9IGJsdWVyZWQoMTAwKSwgIG1hcmdpbj1jKDYsIDYpLCBrZXk9RiwKICAgICAgICAgIHRyYWNlID0gIm5vbmUiLCBkZW5zaXR5LmluZm8gPSAibm9uZSIpCmBgYApJbiBteSBvcGluaW9uLCB0aGUgZXh0ZW5kIG9mIGRhcmtuZXNzIHJlcHJlc2VudCB0aGUgZGVncmVlIG9mIGNvcnJlbGF0aW9uIGJldHdlZW4gdHdvIGVtb3Rpb25zLiAgClRoZXJlZm9yZSwgSSB0aGluayB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBwb3NpdGl2ZSBlbW90aW9ucyBib2NvbWUgaGlnaGVyIGFuZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBuZWdhdGl2ZSBlbW90aW9ucyBib2NvbWUgbG93ZXIgdGhhbiBiZWZvcmUsIHdoaWNoIG1lYW5zICoqcHJlc2lkZW50cyBub3cgZXhwcmVzcyBtb3JlIHBvc2l0aXZlIGVtb3Rpb25zIHRoYW4gYmVmb3JlLioqIAoKVGhlIGZvbGxvd2luZyBwbG90cyBnaXZlIHVzIGEgc3RyYWlnaHQgdmlldyBvZiB0aGUgZGlzdHJpYnV0aW9ucyBvZiBlbW90aW9ucyBpbiB0aGVzZSB0aHJlZSBwZXJpb2RzLiAKYGBge3IsIGZpZy53aWR0aD0yLjcsIGZpZy5oZWlnaHQ9MC45fQpwYXIobWZyb3c9YygxLDMpKSMsIG1hcj1jKDEsMCwyLDApLCBidHk9Im4iLCB4YXh0PSJuIiwgeWF4dD0ibiIsIGZvbnQubWFpbj0xKQplbW8ubWVhbnM9Y29sTWVhbnMoc2VudGVuY2UubGlzdCU+JWZpbHRlcihQZXJpb2Q9PTEpJT4lc2VsZWN0KGFuZ2VyOnRydXN0KT4wLjAxKQpjb2wudXNlPWMoInJlZDIiLCAiZGFya2dvbGRlbnJvZDEiLCAKICAgICAgICAgICAgImNoYXJ0cmV1c2UzIiwgImJsdWV2aW9sZXQiLAogICAgICAgICAgICAiZGFya2dvbGRlbnJvZDIiLCAiZG9kZ2VyYmx1ZTMiLCAKICAgICAgICAgICAgImRhcmtnb2xkZW5yb2QxIiwgImRhcmtnb2xkZW5yb2QxIikKYmFycGxvdChlbW8ubWVhbnNbb3JkZXIoZW1vLm1lYW5zKV0sIGxhcz0yLCBjb2w9Y29sLnVzZVtvcmRlcihlbW8ubWVhbnMpXSwgaG9yaXo9VCwgbWFpbj0iUGVyaW9kIDEiKQplbW8ubWVhbnM9Y29sTWVhbnMoc2VudGVuY2UubGlzdCU+JWZpbHRlcihQZXJpb2Q9PTIpJT4lc2VsZWN0KGFuZ2VyOnRydXN0KT4wLjAxKQpjb2wudXNlPWMoInJlZDIiLCAiZGFya2dvbGRlbnJvZDEiLCAKICAgICAgICAgICAgImNoYXJ0cmV1c2UzIiwgImJsdWV2aW9sZXQiLAogICAgICAgICAgICAiZGFya2dvbGRlbnJvZDIiLCAiZG9kZ2VyYmx1ZTMiLCAKICAgICAgICAgICAgImRhcmtnb2xkZW5yb2QxIiwgImRhcmtnb2xkZW5yb2QxIikKYmFycGxvdChlbW8ubWVhbnNbb3JkZXIoZW1vLm1lYW5zKV0sIGxhcz0yLCBjb2w9Y29sLnVzZVtvcmRlcihlbW8ubWVhbnMpXSwgaG9yaXo9VCwgbWFpbj0iUGVyaW9kIDIiKQplbW8ubWVhbnM9Y29sTWVhbnMoc2VudGVuY2UubGlzdCU+JWZpbHRlcihQZXJpb2Q9PTMpJT4lc2VsZWN0KGFuZ2VyOnRydXN0KT4wLjAxKQpjb2wudXNlPWMoInJlZDIiLCAiZGFya2dvbGRlbnJvZDEiLCAKICAgICAgICAgICAgImNoYXJ0cmV1c2UzIiwgImJsdWV2aW9sZXQiLAogICAgICAgICAgICAiZGFya2dvbGRlbnJvZDIiLCAiZG9kZ2VyYmx1ZTMiLCAKICAgICAgICAgICAgImRhcmtnb2xkZW5yb2QxIiwgImRhcmtnb2xkZW5yb2QxIikKYmFycGxvdChlbW8ubWVhbnNbb3JkZXIoZW1vLm1lYW5zKV0sIGxhcz0yLCBjb2w9Y29sLnVzZVtvcmRlcihlbW8ubWVhbnMpXSwgaG9yaXo9VCwgbWFpbj0iUGVyaW9kIDMiKQpgYGAKCkZyb20gdGhlc2UgcGxvdHMgd2UgY2FuIHNlZSB0aGF0IGluIFBlcmlvZCAxLCBmZWFyIGlzIGluIHRoZSB0aGlyZCBwbGFjZSBvZiB0aGUgZW1vdGlvbiBleHByZXNzaW9uLiBIb3dldmVyLCBpbiBQZXJpb2QgMiwgam95IGJlY29tZSB0aGUgdGhpcmQgcGxhY2Ugb2YgdGhlIGVtb3Rpb24gZXhwcmVzc2lvbi4gSW4gYWRkaXRpb24sIHRoZSBuZWdhdGl2ZSBlbW90aW9ucyBsaWtlIGRpc2d1c3QsIHNhZG5lc3MgYW5kIGFuZ2VyIGhhdmUgYSBsZXNzIHdlaWdodCB0aGFuIGJlZm9yZS4KCioqVGh1cywgSSB3aWxsIHNheSB0aGF0IHByZXNpZGVudHMgdG9kYXkgZXhwcmVzcyBtb3JlIHBvc2l0aXZlIGVtb3Rpb25zIHRoYW4gYmVmb3JlIGFuZCB0aGlzIGNoYW5nZSBpcyBhbHNvIHJlYXNvbmFibGUuKioKClRoZSBmb2xsb3dpbmcgcGxvdCBpbGx1c3RyYXRlcyBteSB2aWV3IGNsZWFybHkuCmBgYHtyLCBmaWcuaGVpZ2h0PTEsIGZpZy53aWR0aD0yLjV9CnBlcmlvZC5zdW1tYXJ5PXRibF9kZihzZW50ZW5jZS5saXN0KSU+JQogIGdyb3VwX2J5KFBlcmlvZCklPiUKICBzdW1tYXJpc2UoCiAgICBuZWdhdGl2ZT1tZWFuKG5lZ2F0aXZlKSwKICAgIHBvc2l0aXZlPW1lYW4ocG9zaXRpdmUpCiAgKQoKZ2dwbG90KHBlcmlvZC5zdW1tYXJ5KSArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBQZXJpb2QsIHkgPSBuZWdhdGl2ZSwgY29sb3IgPSAibmVnYXRpdmUiKSkgKwogIGdlb21fbGluZShtYXBwaW5nID0gYWVzKHggPSBQZXJpb2QsIHkgPSBuZWdhdGl2ZSwgY29sb3IgPSAibmVnYXRpdmUiKSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gUGVyaW9kLCB5ID0gcG9zaXRpdmUsIGNvbG9yID0gInBvc2l0aXZlIikpICsKICBnZW9tX2xpbmUobWFwcGluZyA9IGFlcyh4ID0gUGVyaW9kLCB5ID0gcG9zaXRpdmUsIGNvbG9yID0gInBvc2l0aXZlIikpICsKICBsYWJzKHkgPSAiQXR0aXR1ZGUiKQpgYGAKKipGcm9tIHRoaXMgcGxvdCB3ZSBjYW4gc2VlIHRoYXQgcHJlc2lkZW50cyBhbHdheXMgZXhwcmVzcyBtb3JlIHBvc2l0aXZlIGF0dGl0dWRlIHRoYW4gbmVnYXRpdmUuIEFuZCwgdGhlcmUgaXMgYSB0cmVuZCB0aGF0IHRoZXkgZXhwcmVzcyBtb3JlIHBvc2l0aXZlIGFuZCBsZXNzIG5lZ2F0aXZlIGF0dGl0dWRlIHRoYW4gYmVmb3JlLioqCgojIyBQYXJ0IElJSTogQ2hhbmdlIGluIFRvcGljcyBvZiBQcmVzaWRlbnRzJyBJbmF1Z3J1YWwgU3BlZWNoZXMKCiMjIyBEYXRhIENvbGxlY3Rpb24gYW5kIFByb2Nlc3NpbmcKRm9yIHRvcGljIG1vZGVsaW5nLCBJIHN0aWxsIHVzZSBvbmUgc2VudGVuY2UgYXMgYSB1bml0LiBJIHByZXBhcmUgYSBjb3JwdXMgb2Ygc2VudGVuY2Ugc25pcHBldHMgYXMgZm9sbG93cy4gRm9yIGVhY2ggc3BlZWNoLCBJIHN0YXJ0IHdpdGggc2VudGVuY2VzIGFuZCBwcmVwYXJlIGEgc25pcHBldCB3aXRoIGEgZ2l2ZW4gc2VudGVuY2Ugd2l0aCB0aGUgZmxhbmtpbmcgc2VudGVuY2VzLiAKYGBge3J9CmNvcnB1cy5saXN0PXNlbnRlbmNlLmxpc3RbMjoobnJvdyhzZW50ZW5jZS5saXN0KS0xKSwgXQpzZW50ZW5jZS5wcmU9c2VudGVuY2UubGlzdCRzZW50ZW5jZXNbMToobnJvdyhzZW50ZW5jZS5saXN0KS0yKV0Kc2VudGVuY2UucG9zdD1zZW50ZW5jZS5saXN0JHNlbnRlbmNlc1szOihucm93KHNlbnRlbmNlLmxpc3QpLTEpXQpjb3JwdXMubGlzdCRzbmlwcGV0cz1wYXN0ZShzZW50ZW5jZS5wcmUsIGNvcnB1cy5saXN0JHNlbnRlbmNlcywgc2VudGVuY2UucG9zdCwgc2VwPSIgIikKcm0ucm93cz0oMTpucm93KGNvcnB1cy5saXN0KSlbY29ycHVzLmxpc3Qkc2VudC5pZD09MV0Kcm0ucm93cz1jKHJtLnJvd3MsIHJtLnJvd3MtMSkKY29ycHVzLmxpc3Q9Y29ycHVzLmxpc3RbLXJtLnJvd3MsIF0KCiMgVGV4dCBtaW5pbmcKZG9jcyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKGNvcnB1cy5saXN0JHNuaXBwc2V0cykpCgojVGV4dCBiYXNpYyBwcm9jZXNzaW5nCiNyZW1vdmUgcG90ZW50aWFsbHkgcHJvYmxlbWF0aWMgc3ltYm9scwpkb2NzIDwtdG1fbWFwKGRvY3MsY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKCiNyZW1vdmUgcHVuY3R1YXRpb24KZG9jcyA8LSB0bV9tYXAoZG9jcywgcmVtb3ZlUHVuY3R1YXRpb24pCgojU3RyaXAgZGlnaXRzCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHJlbW92ZU51bWJlcnMpCgojcmVtb3ZlIHN0b3B3b3Jkcwpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpCgojcmVtb3ZlIHdoaXRlc3BhY2UKZG9jcyA8LSB0bV9tYXAoZG9jcywgc3RyaXBXaGl0ZXNwYWNlKQoKI1N0ZW0gZG9jdW1lbnQKZG9jcyA8LSB0bV9tYXAoZG9jcyxzdGVtRG9jdW1lbnQpCmBgYAoKIyMjIERhdGEgQW5hbHlzaXMgLS0tIFRvcGljIE1vZGVsaW5nCgpTdGVwIDE6IEdlbmdlcmF0ZSBkb2N1bWVudC10ZXJtIG1hdHJpY2VzLiAKCmBgYHtyfQpkdG0gPC0gRG9jdW1lbnRUZXJtTWF0cml4KGRvY3MpCiNjb252ZXJ0IHJvd25hbWVzIHRvIGZpbGVuYW1lcyAKZm9yIChpIGluIDE6bnJvdyhjb3JwdXMubGlzdCkpIHsKICAgIGNvcnB1cy5saXN0JEZpbGVbaV0gPC0gc3Vic3RyKGNvcnB1cy5saXN0JEZpbGVbaV0sIHN0YXJ0ID0gNiwgc3RvcCA9IG5jaGFyKGNvcnB1cy5saXN0JEZpbGVbaV0pIC0gNCl9CnJvd25hbWVzKGR0bSkgPC0gcGFzdGUoY29ycHVzLmxpc3QkRmlsZSwgY29ycHVzLmxpc3Qkc2VudC5pZCwgc2VwPSJfIikKCnJvd1RvdGFscyA8LSBhcHBseShkdG0gLCAxLCBzdW0pICNGaW5kIHRoZSBzdW0gb2Ygd29yZHMgaW4gZWFjaCBEb2N1bWVudAoKZHRtICA8LSBkdG1bcm93VG90YWxzPiAwLCBdCmNvcnB1cy5saXN0PWNvcnB1cy5saXN0W3Jvd1RvdGFscz4wLCBdCgpgYGAKClN0ZXAgMjogUnVuIExEQSB3aXRoIDEwIHRvcGljcyAgCgpUaGUgZm9sbG93aW5nIHRhYmxlIHNob3dzIHRoZSBudW1iZXIgb2Ygc2VudGVuY2VzIGluIGVhY2ggdG9waWMuICAKYGBge3J9CiNTZXQgcGFyYW1ldGVycyBmb3IgR2liYnMgc2FtcGxpbmcKYnVybmluIDwtIDQwMDAKaXRlciA8LSAyMDAwCnRoaW4gPC0gNTAwCnNlZWQgPC1saXN0KDIwMDMsNSw2MywxMDAwMDEsNzY1KQpuc3RhcnQgPC0gNQpiZXN0IDwtIFRSVUUKCiNOdW1iZXIgb2YgdG9waWNzCmsgPC0gMTAKCiNSdW4gTERBIHVzaW5nIEdpYmJzIHNhbXBsaW5nCmxkYU91dCA8LUxEQShkdG0sIGssIG1ldGhvZD0iR2liYnMiLCBjb250cm9sPWxpc3QobnN0YXJ0PW5zdGFydCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gc2VlZCwgYmVzdD1iZXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVybmluID0gYnVybmluLCBpdGVyID0gaXRlciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGluPXRoaW4pKQojd3JpdGUgb3V0IHJlc3VsdHMKI2RvY3MgdG8gdG9waWNzCmxkYU91dC50b3BpY3MgPC0gYXMubWF0cml4KHRvcGljcyhsZGFPdXQpKQp0YWJsZShjKDE6aywgbGRhT3V0LnRvcGljcykpCndyaXRlLmNzdihsZGFPdXQudG9waWNzLGZpbGU9cGFzdGUoIn4vRGVza3RvcC9DVV9TdGF0cy8yMDE4IFNwcmluZy9HUjUyNDMgQURTL1Byb2plY3QgMS9kYXRhLy9vdXRwdXQvTERBR2liYnMiLGssIkRvY3NUb1RvcGljcy5jc3YiKSkKCiN0b3AgMjAgdGVybXMgaW4gZWFjaCB0b3BpYwpsZGFPdXQudGVybXMgPC0gYXMubWF0cml4KHRlcm1zKGxkYU91dCwyMCkpCndyaXRlLmNzdihsZGFPdXQudGVybXMsZmlsZT1wYXN0ZSgifi9EZXNrdG9wL0NVX1N0YXRzLzIwMTggU3ByaW5nL0dSNTI0MyBBRFMvUHJvamVjdCAxL2RhdGEvL291dHB1dC9MREFHaWJicyIsaywiVG9waWNzVG9UZXJtcy5jc3YiKSkKCiNwcm9iYWJpbGl0aWVzIGFzc29jaWF0ZWQgd2l0aCBlYWNoIHRvcGljIGFzc2lnbm1lbnQKdG9waWNQcm9iYWJpbGl0aWVzIDwtIGFzLmRhdGEuZnJhbWUobGRhT3V0QGdhbW1hKQp3cml0ZS5jc3YodG9waWNQcm9iYWJpbGl0aWVzLGZpbGU9cGFzdGUoIn4vRGVza3RvcC9DVV9TdGF0cy8yMDE4IFNwcmluZy9HUjUyNDMgQURTL1Byb2plY3QgMS9kYXRhLy9vdXRwdXQvTERBR2liYnMiLGssIlRvcGljUHJvYmFiaWxpdGllcy5jc3YiKSkKYGBgCgpJIGFsc28gZ2l2ZSB0aGUgdG9wIDIwIG1vc3QgcG9wdWxhciB3b3JkcyBpbiBlYWNoIHRvcGljLiAKYGBge3J9CmxkYU91dC50ZXJtcwpgYGAKCkJhc2VkIG9uIHRoZSBtb3N0IHBvcHVsYXIgdGVybXMgYW5kIHRoZSBtb3N0IHNhbGllbnQgdGVybXMgZm9yIGVhY2ggdG9waWMsIEkgYXNzaWduIGEgaGFzaHRhZyB0byBlYWNoIHRvcGljLiBUaGlzIHBhcnQgaXMgc3ViamVjdGl2ZSBiZWNhdXNlIEkgc2V0IHVwIHRoZXNlIHRvcGljcyBtYW51YWxseS4KYGBge3J9CnRvcGljcy5oYXNoPWMoIkdvdmVybiIsICJFY29ub215IiAsICJSZXNwb25zaWJpbGl0eSIsICJQZWFjZSIsICJVbml0eSIsICJGcmVlZG9tIiwgIkRlZmVuc2UiLCAiUmVmb3JtYXRpb24iLCAiQmVsaWVmIiwgIlBhdHJpb3Rpc20iKSAKCmNvcnB1cy5saXN0JGxkYXRvcGljPWFzLnZlY3RvcihsZGFPdXQudG9waWNzKQpjb3JwdXMubGlzdCRsZGFoYXNoPXRvcGljcy5oYXNoW2xkYU91dC50b3BpY3NdCgpjb2xuYW1lcyh0b3BpY1Byb2JhYmlsaXRpZXMpPXRvcGljcy5oYXNoCmNvcnB1cy5saXN0LmRmPWNiaW5kKGNvcnB1cy5saXN0LCB0b3BpY1Byb2JhYmlsaXRpZXMpCmBgYAoKIyMjIyBGcmVxdWVuY2llcyBvZiB0b3BpY3MgaW4gZGlmZmVyZW50IHBlcmlvZHMuCgpUaGUgZm9sbG93aW5nIHBpZSBwbG90cyBzaG93IHRoZSBkaXN0cmlidXRpb25zIG9mIHRoZSB0b3BpY3Mgb2Ygc3BlZWNoZXMgaW4gdGhlc2UgdGhyZWUgcGVyaW9kcy4KYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTN9CnRvcGljLjEgPC0gY29ycHVzLmxpc3QkbGRhdG9waWNbY29ycHVzLmxpc3QkUGVyaW9kID09IDFdCnRvcGljLnByb3AuMSA8LSBhcy5pbnRlZ2VyKHRhYmxlKHRvcGljLjEpKS9sZW5ndGgodG9waWMuMSkKcGVyMSA8LSByb3VuZCh0b3BpYy5wcm9wLjEgKiAxMDAsIDIpCnRvcGljLnBlci4xICA8LSBwYXN0ZShwZXIxLCAiJSIsIHNlcD0iIikKcGVyaW9kMSA8LSBkYXRhLmZyYW1lKFBlcmNlbnRhZ2UgPXRvcGljLnByb3AuMSwgVG9waWMgPSB0b3BpY3MuaGFzaCwgUGVyY2VudD10b3BpYy5wZXIuMSkKCgp0b3BpYy4yIDwtIGNvcnB1cy5saXN0JGxkYXRvcGljW2NvcnB1cy5saXN0JFBlcmlvZCA9PSAyXQp0b3BpYy5wcm9wLjIgPC0gYXMuaW50ZWdlcih0YWJsZSh0b3BpYy4yKSkvbGVuZ3RoKHRvcGljLjIpCnBlcjIgPC0gcm91bmQodG9waWMucHJvcC4yICogMTAwLCAyKQp0b3BpYy5wZXIuMiAgPC0gcGFzdGUocGVyMiwgIiUiLCBzZXA9IiIpCnBlcmlvZDIgPC0gZGF0YS5mcmFtZShQZXJjZW50YWdlID10b3BpYy5wcm9wLjIsIFRvcGljID0gdG9waWNzLmhhc2gsIFBlcmNlbnQ9dG9waWMucGVyLjIpCgoKdG9waWMuMyA8LSBjb3JwdXMubGlzdCRsZGF0b3BpY1tjb3JwdXMubGlzdCRQZXJpb2QgPT0gM10KdG9waWMucHJvcC4zIDwtIGFzLmludGVnZXIodGFibGUodG9waWMuMykpL2xlbmd0aCh0b3BpYy4zKQpwZXIzIDwtIHJvdW5kKHRvcGljLnByb3AuMyAqIDEwMCwgMikKdG9waWMucGVyLjMgIDwtIHBhc3RlKHBlcjMsICIlIiwgc2VwPSIiKQpwZXJpb2QzIDwtIGRhdGEuZnJhbWUoUGVyY2VudGFnZSA9dG9waWMucHJvcC4zLCBUb3BpYyA9IHRvcGljcy5oYXNoLCBQZXJjZW50PXRvcGljLnBlci4zKQoKCnBhcihtZnJvdz1jKDEsMykpCiMgUGxvdCB0aGUgY2hhcnQuCnBpZSh0b3BpYy5wcm9wLjEsIGxhYmVscyA9IHRvcGljLnBlci4xLCBjb2wgPSByYWluYm93KGxlbmd0aCh0b3BpYy5wZXIuMSkpLCBtYWluID0gIlRvcGljIERpc3RyaWJ1dGlvbiBpbiBQZXJpb2QgMSIpCmxlZ2VuZCgidG9wcmlnaHQiLCB0b3BpY3MuaGFzaCwgY2V4ID0gMC44LCBmaWxsID0gcmFpbmJvdyhsZW5ndGgodG9waWMucGVyLjEpKSkKCnBpZSh0b3BpYy5wcm9wLjIsIGxhYmVscyA9IHRvcGljLnBlci4yLCBjb2wgPSByYWluYm93KGxlbmd0aCh0b3BpYy5wZXIuMikpLCBtYWluID0gIlRvcGljIERpc3RyaWJ1dGlvbiBpbiBQZXJpb2QgMiIpCmxlZ2VuZCgidG9wcmlnaHQiLCB0b3BpY3MuaGFzaCwgY2V4ID0gMC44LCBmaWxsID0gcmFpbmJvdyhsZW5ndGgodG9waWMucGVyLjIpKSkKCnBpZSh0b3BpYy5wcm9wLjMsIGxhYmVscyA9IHRvcGljLnBlci4zLCBjb2wgPSByYWluYm93KGxlbmd0aCh0b3BpYy5wZXIuMykpLCBtYWluID0gIlRvcGljIERpc3RyaWJ1dGlvbiBpbiBQZXJpb2QgMyIpCmxlZ2VuZCgidG9wcmlnaHQiLCB0b3BpY3MuaGFzaCwgY2V4ID0gMC44LCBmaWxsID0gcmFpbmJvdyhsZW5ndGgodG9waWMucGVyLjMpKSkKCgpgYGAKRnJvbSB0aGUgcGxvdHMsIHdlIGtub3cgdGhhdCBSZXNwb25zaWJpbGl0eSBhbmQgR292ZXJuIHBsYXkgaW1wb3J0YW50IHJvbGVzIGluIFBlcmlvZCAxLCBQZWFjZSBhbmQgRGVuZmVuc2UgcGxheSBpbXBvcnRhbnQgcm9sZXMgaW4gYm90aCBQZXJpb2QgMiBhbmQgUGVyaW9kIDMuIEhvd2V2ZXIsIFBlYWNlIGFuZCBEZW5mZW5zZSBjb3ZlciBvdmVyIDIvMyB0b3BpYyBpbiBQZXJpb2QgMy4gCgoqKkkgdGhpbmsgdGhpcyBjaGFuZ2Ugb2YgdG9waWNzIGlzIGFsc28gY29uc2lzdGVudCB3aXRoIHRoZSBkZXZlbG9wbWVudCBvZiBvdXIgc29jaWV0eSwgc2luY2UgcGVvcGxlIGNhcmUgbW9yZSBhYm91dCBsaXZpbmcgYSBwZWFjZWZ1bCBsaWZlIG5vdy4qKgoKIyMgQ29uY2x1c2lvbjoKRnJvbSBteSBzdHVkeSwgSSB3aWxsIGRyYXcgYSBjb25jbHVzaW9uIHRoYXQgdGhlIHRyZW5kIG9mIHByZXNpZGVudHMnIHNwZWVjaGVzIGZyb20gMTc4OSB0byAyMDE3IGNvcnJlc3BvbmQgd2l0aCB0aGUgZGV2ZWxvcG1lbnQgb2Ygb3VyIGh1bWFuIGJlaGF2aW91cnMuICAKCjEuIFNlbnRlbmNlcyBiZWNvbWUgc2hvcnRlciB0aGFuIGJlZm9yZSwgd2hpY2ggaW1wbGllcyB0aGF0IHBlb3BsZSBhcmUgcHVyc3VpbmcgYW4gc2ltcGxlciB3YXkgdG8gZXhwcmVzcyB0aGVtc2VsdmVzLiAgCgoyLiBMZXNzIHJhZGljYWwgaW4gc2VudGltZW50IG1lYW5zIHBlb3BsZSBub3cgY2FuIGNvbnRyb2wgdGhlaXIgZW1vdGlvbiB3ZWxsIGFuZCBjYW4gYWx3YXlzIGtlZXAgY2FsbS4gSW4gYWRkaXRpb24sIHBlb3BsZSBub3cgYmVjb21lIG1vcmUgcG9zc2l0aXZlIHRoYW4gYmVmb3JlLiAgCgozLiBUb3BpYyBjaGFuZ2Ugb2Ygc3BlZWNoZXMgcmVmbGVjdHMgb3VyIHRob3VnaHRzLiBJdCBzaG93cyB3aGF0IGtpbmQgb2YgbGlmZSB3ZSBhcmUgbGl2aW5nIGluIG9yIHdlIHdhbnQgdG8gbGl2ZSBpbi4KCiMjIEFwcGVuZGl4OiBXb3JkIENsb3VkCgoqKkluIHRoZSBlbmQsIEkgd2FudCB0byBzaG93IHRoZSB3b3JkIGNsb3VkcyBvZiBzcGVlY2hlcyBpbiB0aHJlZSBkaWZmZXJlbnQgcGVyaW9kcy4qKiAgCihUaGlzIGlzIG5vdCBwYXJ0IG9mIG15IHN0b3J5LCBJIGp1c3QgZG8gdGhpcyBmb3IgZnVuLikKCiMjIyBEYXRhIENvbGxlY3Rpb24gYW5kIFByb2Nlc3NpbmcgIAoKU3RlcCAwOiBJbnN0YWxsIGFuZCBsb2FkIGxpYnJhcmllcwpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGFja2FnZXMudXNlZD1jKCJ0bSIsICJ3b3JkY2xvdWQiLCAiUkNvbG9yQnJld2VyIiwgCiAgICAgICAgICAgICAgICAiZHBseXIiLCAidHlkeXRleHQiKQoKIyBjaGVjayBwYWNrYWdlcyB0aGF0IG5lZWQgdG8gYmUgaW5zdGFsbGVkLgpwYWNrYWdlcy5uZWVkZWQ9c2V0ZGlmZihwYWNrYWdlcy51c2VkLCAKICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJzZWN0KGluc3RhbGxlZC5wYWNrYWdlcygpWywxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrYWdlcy51c2VkKSkKIyBpbnN0YWxsIGFkZGl0aW9uYWwgcGFja2FnZXMKaWYobGVuZ3RoKHBhY2thZ2VzLm5lZWRlZCk+MCl7CiAgaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlcy5uZWVkZWQsIGRlcGVuZGVuY2llcyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICByZXBvcz0naHR0cDovL2NyYW4udXMuci1wcm9qZWN0Lm9yZycpCn0KCmxpYnJhcnkodG0pCmxpYnJhcnkod29yZGNsb3VkKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dGV4dCkKYGBgCgpTdGVwIDE6IFJlYWQgaW4gdGhlIHNwZWVjaGVzCmBgYHtyfQpzcGVlY2hlcz1saXN0LmZpbGVzKHBhdGggPSBmb2xkZXIucGF0aCwgcGF0dGVybiA9ICIqLnR4dCIpCnByZXgub3V0PXN1YnN0cihzcGVlY2hlcywgNiwgbmNoYXIoc3BlZWNoZXMpLTQpCgpmZi5hbGwubzwtQ29ycHVzKERpclNvdXJjZShmb2xkZXIucGF0aCkpCmBgYAoKU3RlcCAyOiBUZXh0IHByb2Nlc3NpbmcKYGBge3J9Cm9yZCA8LSBhcy5mYWN0b3Ioc3BlZWNoLmxpc3QkRmlsZSkKbGV2ZWxzKG9yZCkgPC0gMTo1OApmZi5hbGwgPC0gZmYuYWxsLm9bYXMuaW50ZWdlcihvcmQpXQpmZi5hbGw8LXRtX21hcChmZi5hbGwsIHN0cmlwV2hpdGVzcGFjZSkKZmYuYWxsPC10bV9tYXAoZmYuYWxsLCBjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQpmZi5hbGw8LXRtX21hcChmZi5hbGwsIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkKZmYuYWxsPC10bV9tYXAoZmYuYWxsLCByZW1vdmVXb3JkcywgY2hhcmFjdGVyKDApKQpmZi5hbGw8LXRtX21hcChmZi5hbGwsIHJlbW92ZVB1bmN0dWF0aW9uKQoKZmYuMSA8LSBmZi5hbGxbMToyMF0KZmYuMiA8LSBmZi5hbGxbMjE6NDBdCmZmLjMgPC0gZmYuYWxsWzQxOjU4XQoKdGRtLjE8LVRlcm1Eb2N1bWVudE1hdHJpeChmZi4xKQp0ZG0uMjwtVGVybURvY3VtZW50TWF0cml4KGZmLjIpCnRkbS4zPC1UZXJtRG9jdW1lbnRNYXRyaXgoZmYuMykKCnRkbS50aWR5LjE9dGlkeSh0ZG0uMSkKdGRtLnRpZHkuMj10aWR5KHRkbS4yKQp0ZG0udGlkeS4zPXRpZHkodGRtLjMpCgp0ZG0ub3ZlcmFsbC4xPXN1bW1hcmlzZShncm91cF9ieSh0ZG0udGlkeS4xLCB0ZXJtKSwgc3VtKGNvdW50KSkKdGRtLm92ZXJhbGwuMj1zdW1tYXJpc2UoZ3JvdXBfYnkodGRtLnRpZHkuMiwgdGVybSksIHN1bShjb3VudCkpCnRkbS5vdmVyYWxsLjM9c3VtbWFyaXNlKGdyb3VwX2J5KHRkbS50aWR5LjMsIHRlcm0pLCBzdW0oY291bnQpKQpgYGAKCgojIyMgRGF0YSBBbmFseXNpcyAtLS0gV29yZGNsb3VkcyAgCgoqKk1ha2Ugd29yZGNsb3VkcyBvZiBzcGVlY2hlcyBpbiB0aHJlZSBkaWZmZXJlbnQgcGVyaW9kcyB1c2luZyBURi1JREYgd2VpZ2h0ZWQgZG9jdW1lbnQtdGVybSBtYXRyaWNlcy4qKiAgCgpBcyBJIHdvdWxkIGxpa2UgdG8gaWRlbnRpZnkgaW50ZXJlc3Rpbmcgd29yZHMgZm9yIHNwZWVjaGVzIGluIGVhY2ggcGVyaW9kLCBJIHVzZSBbVEYtSURGXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9UZiVFMiU4MCU5M2lkZikgdG8gd2VpZ2ggZWFjaCB0ZXJtIHdpdGhpbiBzcGVlY2hlcyBpbiBlYWNoIHBlcmlvZC4gSXQgaGlnaGxpZ2h0cyB0ZXJtcyB0aGF0IGFyZSBtb3JlIHdpZGVseS11c2VkIGluIGEgcGFydGljdWxhciBwZXJpb2QuIAoKYGBge3J9CmR0bS4xIDwtIERvY3VtZW50VGVybU1hdHJpeChmZi4xLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KHdlaWdodGluZyA9IGZ1bmN0aW9uKHgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodFRmSWRmKHgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemUgPUZBTFNFKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9wd29yZHMgPSBUUlVFKSkKZmYuZHRtLjE9dGlkeShkdG0uMSkKCmR0bS4yIDwtIERvY3VtZW50VGVybU1hdHJpeChmZi4yLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KHdlaWdodGluZyA9IGZ1bmN0aW9uKHgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodFRmSWRmKHgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemUgPUZBTFNFKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9wd29yZHMgPSBUUlVFKSkKZmYuZHRtLjI9dGlkeShkdG0uMikKCmR0bS4zIDwtIERvY3VtZW50VGVybU1hdHJpeChmZi4zLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KHdlaWdodGluZyA9IGZ1bmN0aW9uKHgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodFRmSWRmKHgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemUgPUZBTFNFKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9wd29yZHMgPSBUUlVFKSkKZmYuZHRtLjM9dGlkeShkdG0uMykKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KcGFyKG1mcm93PWMoMSwzKSxtYXI9YygxLDEsMSwxKSkKd29yZGNsb3VkKGZmLmR0bS4xJHRlcm0sIGZmLmR0bS4xJGNvdW50LAogICAgICAgICAgc2NhbGU9Yyg1LDAuNSksCiAgICAgICAgICBtYXgud29yZHM9MTAwLAogICAgICAgICAgbWluLmZyZXE9MSwKICAgICAgICAgIHJhbmRvbS5vcmRlcj1GQUxTRSwKICAgICAgICAgIHJvdC5wZXI9MC4zLAogICAgICAgICAgdXNlLnIubGF5b3V0PVQsCiAgICAgICAgICByYW5kb20uY29sb3I9RkFMU0UsCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg5LCJCbHVlcyIpKQp0ZXh0KDAuNSwtMC4xLCJQZXJpb2QgMSIsY29sPSJibGFjayIsY2V4PTEuMikKCndvcmRjbG91ZChmZi5kdG0uMiR0ZXJtLCBmZi5kdG0uMiRjb3VudCwKICAgICAgICAgIHNjYWxlPWMoNSwwLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwKICAgICAgICAgIG1pbi5mcmVxPTEsCiAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICByb3QucGVyPTAuMywKICAgICAgICAgIHVzZS5yLmxheW91dD1ULAogICAgICAgICAgcmFuZG9tLmNvbG9yPUZBTFNFLAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOSwiUmVkcyIpKQp0ZXh0KDAuNSwtMC4xLCJQZXJpb2QgMiIsY29sPSJibGFjayIsY2V4PTEuMikKCndvcmRjbG91ZChmZi5kdG0uMyR0ZXJtLCBmZi5kdG0uMyRjb3VudCwKICAgICAgICAgIHNjYWxlPWMoNSwwLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwKICAgICAgICAgIG1pbi5mcmVxPTEsCiAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICByb3QucGVyPTAuMywKICAgICAgICAgIHVzZS5yLmxheW91dD1ULAogICAgICAgICAgcmFuZG9tLmNvbG9yPUZBTFNFLAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOSwiR3JlZW5zIikpCnRleHQoMC41LC0wLjEsIlBlcmlvZCAzIixjb2w9ImJsYWNrIixjZXg9MS4yKQpgYGAKCgoKCgoKCgoKCgo=